/******************************************************************************
 * This file is part of libemb.
 *
 * libemb is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * libemb is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with libemb.  If not, see <http://www.gnu.org/licenses/>.
 *
 * Project: Embedme
 * Author : FergusZeng
 * Email  : cblock@126.com
 * git	  : https://git.oschina.net/cblock/embedme
 * Copyright 2014~2020 @ ShenZhen ,China
*******************************************************************************/
#include "Logger.h"
#include "Tracer.h"

namespace libemb{

#define LOG_BUFLEN_MAX 1024
#define LOG_ROOT_DIR   "/tmp/log/"
Logger::Logger()
{
	m_logBufPtr = std::make_unique<char[]>(LOG_BUFLEN_MAX);
}

Logger::~Logger()
{
	for(auto kv : m_logMap)
	{
		kv.second->close();
	}
	m_logMap.clear();
}

void Logger::setRoot(std::string logDir)
{
	m_logDir = logDir;
}

bool Logger::openLog(std::string logName)
{
	if (m_logDir.empty())
	{
		m_logDir = LOG_ROOT_DIR;
	}
	if (Directory::exists(CSTR(m_logDir)) || Directory::createDir(CSTR(m_logDir), true))
	{
		bool isNew = false;
		std::shared_ptr<File> logFile;
		std::string logFileName = m_logDir+std::string("/")+logName+std::string(".log");
		auto iter = m_logMap.find(logName);
		if (iter!=m_logMap.end())
		{
			logFile = iter->second; 
			if (logFile->isOpen())
			{
				return true;
			}
		}
		else
		{
			logFile =std::make_shared<File>();
			isNew = true;
		}
		
		if(!logFile->open(CSTR(logFileName), IO_MODE_REWR_ORNEW))
		{
			TRACE_ERR_CLASS("cannot create log: %s\n",CSTR(logName));
			return false;
		}
		if (isNew)
		{
			m_logMap.insert(std::make_pair(logName,logFile));
		}
		return true;
	}
	TRACE_ERR_CLASS("create log error, no log dir:%s\n",CSTR(m_logDir));
	return false;
}

void Logger::closeLog(std::string logName)
{
	auto logFile = getLogFile(logName);
	if(!logFile)
	{
		return;
	}
	logFile->close();
}

bool Logger::log(std::string logName,const char* format,...)
{
	auto logFile = getLogFile(logName);
	if(!logFile || !logFile->isOpen())
	{
		TRACE_ERR_CLASS("log file not open!\n");
		return false;
	}
	va_list argp;
    va_start(argp,format);
	int size = LOG_BUFLEN_MAX-1;
	char* buf = m_logBufPtr.get();
    size = vsnprintf(buf,size,format,argp);
	va_end(argp);
    if (size>0) 
    {
        if (size>=LOG_BUFLEN_MAX) /* 超过长度了 */
        {
            buf[LOG_BUFLEN_MAX-5]='.';
            buf[LOG_BUFLEN_MAX-4]='.';
            buf[LOG_BUFLEN_MAX-3]='.';
            buf[LOG_BUFLEN_MAX-2]='\n';
            buf[LOG_BUFLEN_MAX-1]=0;
            size = LOG_BUFLEN_MAX;
        }
		logFile->writeData(buf, size);
    }
	return true;
}

std::shared_ptr<File> Logger::getLogFile(std::string logName)
{
	auto iter = m_logMap.find(logName);
	if (iter==m_logMap.end())
	{
		return nullptr;
	}
	return iter->second;
}

}

